/*
 * Copyright by LunaSec (owned by Refinery Labs, Inc)
 *
 * Licensed under the Business Source License v1.1
 * (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * https://github.com/lunasec-io/lunasec/blob/master/licenses/BSL-LunaTrace.txt
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import {
  Analysis_Finding_Source_Enum,
  Analysis_Finding_Type_Enum,
  GetTreeFromBuildQuery,
  Project_Folder_Settings,
} from '../../hasura-api/generated';

export interface VulnerableEdge {
  edgeId: string;
  vulnerabilityIds: string[];
}

export interface Manifest {
  path?: string | null;
  manifest_dependency_node?: ManifestRootNode | null;
  child_edges_recursive?: ManifestEdge[] | null;
}

export interface ManifestRootNode {
  id: string;
}

export interface ManifestEdge {
  child_id: string;
  parent_id: string;
  id: string;
  child: ManifestNode;
  analysis_results: AnalysisResult[];
}

export interface AnalysisResult {
  finding_source_version: number;
  finding_source: Analysis_Finding_Source_Enum;
  finding_type: Analysis_Finding_Type_Enum;
  locations: AnalysisResultLocation[];
}

export interface AnalysisResultLocation {
  id: string;
  path: string;
  start_row: number;
  start_column: number;
  end_row: number;
  end_column: number;
}

export interface ManifestNode {
  id: string;
  range: string;
  release_id: string;
  release: ManifestRelease;
  labels?: Record<string | number | symbol, unknown>;
}

export interface ManifestRelease {
  id: string;
  version: string;
  package: ManifestReleasePackage;
}

interface ManifestReleasePackage {
  affected_by_vulnerability: PackageVulnerability[];
  name: string;
  package_manager: string;
}

export interface RawGuide {
  id: string;
  title: string;
  summary: string;
}

export interface Severity {
  source: string;
  type: string;
  score: string;
}

export interface PackageVulnerability {
  vulnerability: {
    id: string;
    severity_name?: string | null;
    cvss_score?: number | null;
    source: string;
    source_id: string;
    summary?: string | null;
    guide_vulnerabilities: Array<{ guide: VulnerabilityGuide }>;
    cwes: VulnerabilityCwe[];
    severities: Severity[];
  };
  ranges: PackageVulnerabilityRange[];
}

export type FolderSettings = NonNullable<GetTreeFromBuildQuery['builds_by_pk']>['project']['project_folder_settings'];
export type CvssAdjustments =
  FolderSettings[number]['folder_environmental_adjustments'][number]['cvss_environmental_adjustment'];

interface VulnerabilityCwe {
  id: string;
  cwe: Cwe;
}

interface Cwe {
  id: number;
  name: string;
  description: string;
}

interface PackageVulnerabilityRange {
  introduced?: string | null;
  fixed?: string | null;
}

export interface VulnerabilityGuide {
  id: string;
  title: string;
  summary: string;
}

// The incoming data from the database we use to match ignores to vulns
export interface IgnoredVulnerability {
  vulnerability_id: string;
  locations: string[];
  note: string;
}

// The ignore information we send to the client
export interface IgnoredVulnerabilityCause {
  // Removed these fields because path-match ignores dont have them and the client doesn't use them for anything yet anyway
  // vulnerability_id: string;
  // locations: string[];
  note: string;
}

export interface VulnerableManifestNode extends ManifestNode {
  reachable: Analysis_Finding_Type_Enum;
  locations: AnalysisResultLocation[];
}

export interface Adjustment {
  adjusted_from_cvss_score: number | null | undefined;
  adjusted_from_severity_name: string | null | undefined;
  path_matched: string;
  adjustments_applied: string[];
}

export type DependencyChain = VulnerableManifestNode[];

export interface TriagedPackageVulnerability extends PackageVulnerability {
  trivially_updatable_to: string | null; // We add this by determining something can be updated to a non-vulnerable version without violating semver
  path: string;
  beneath_minimum_severity: boolean;
  fix_versions: string[];
  ignored: boolean;
  ignored_vulnerability: IgnoredVulnerabilityCause | undefined;
  adjustment?: Adjustment;
}

export interface VulnerableRelease {
  release: ManifestRelease;
  severity: string;
  beneath_minimum_severity: boolean; // if all its vulns are beneath severity, mark the release as beneath severity as well
  chains: DependencyChain[];
  cvss: number | null; // the highest rating from all the vulns on the release, used for giving the user an at-a-glance rating
  dev_only: boolean;
  affected_by: TriagedPackageVulnerability[];
  trivially_updatable: 'no' | 'partially' | 'yes';
  paths: string[];
  guides: RawGuide[];
  fix_versions: string[];
  adjustment?: Adjustment;
}
